/*************************************************************************
//        Symbolic Circuit Analysis With TPDDs (Tree Pair Decision Diagram)
// tpddnode.cpp
//Class Definition for tpddnode.
// tpddnode is the nodes in TPDD.
//
// CHEN Weiwei		GShi	06/03/31
// School of Microelectronics, Shanghai Jiaotong Univ.
// {chenweiwei, shiguoyong}@ic.sjtu.edu.cn
**************************************************************************/

#ifndef TPDDNODE_H	
#define TPDDNODE_H

#include "tpdd_struct.h"
#include "tpdd_global.h"
#include "tnode.h"
#include "subtree.h"
#include "complex_t.h"
#include <vector>
#include "option.h"
#include <cstdio>

class scoeffNode;
class sexpTpddNode;

/**
	The class for the label of the tpdd node in TPDD reduce process.
*/
class tpddnode_tag : public Comparable   
{                                       
public:
	/// The label of the tpdd node pointed by the short edge.
		int label_left;       
		
	/// The label of the tpdd node pointed by the open edge.
		int label_right;                      

	/// The label of the current tpdd node.
		int label;

	/**
		The constructor of tpddnode_tag.
		@param tl: the label of the short child node.
		@param tr: the label of the open child node.
	*/
	tpddnode_tag(int tl = 0, int tr = 0)
	{
		label_left = tl;
		label_right = tr;
		label = 0;
	};

	/**
		The destructor of tpddnode_tag.
	*/
	~tpddnode_tag(){};

	/**
	    The function to get the hash value.
		The hash value is generated by the labels of the short child node and open child node.
	*/
	virtual unsigned Hash(unsigned i = 0)
	{
		return ((label_left << 3) ^ (label_right << 7));
	}

	/**
	    The function to get the entry of the hash table.
	*/
	unsigned HashId()
	{
		return abs(label_left * TAG_PRIME1 + label_right) % TAG_PRIME2;
	}

	/**
	    The function to compare two tpddnode_tags with the same hash value.
		@param p: the tpddnode_tag with the same hash value with this tpddnode_tag.
	*/
	virtual integer Compare(Comparable *p);


	/**
		The function to set all the label in one tpddnode_tag.
		@param tl: the label of the short child node.
		@param tr: the label of the open child node.
		@param ll: the label of current tpdd node.
	*/
	void setLRL(int tl, int tr, int ll)    // set all the labels
	{
		label_left = tl;
		label_right = tr;
		label = ll;
	};
};

/**
	The class for the Nodes in Tree Pair Decision Diagram
*/

class tpddnode : public Tnode
{
private:
	///  symbol index for each node.
		int symbIndex : 24;

	///  the sign attached to the short edge.
		short signS		: 2;

	///  the sign attached to the open edge.
		short signO		: 2;

	///  the flag for identifying whether the node is visited or not.
		bool visit_flag : 1;

	///  the order of the s-variable for approximate analysis.
		short order     : 10;

	///  the pointer to the left reduced graph.
		subtree *pLTree;

	///  the pointer to the right reduece graph.
		subtree *pRTree;

	///  the pointer to the tpdd node issued by the short edge.
		tpddnode * pShort;

	///  the pointer to the tpdd node issued by the open edge.
		tpddnode * pOpen;

	///  the pointer to the next tpdd node in TPDD reducing.
		tpddnode * pNext;

	///  the label tag for TPDD reducing.
		tpddnode_tag pTag;

	///  the expression value of the node and its subtree.		       
		complex_t *val_ptr;			

	///  the number of the terms represented by the subgraph rooted by this tpdd node.
		double termN;


public:
		double aT;
		sexpTpddNode* pSExpNode;

public:
	/**
		The default constructor of a tpdd node.		
	*/
		tpddnode();

	/**
		The constructor with parameters for a tpdd node.
		@param SymbI: the index of the symbol represented this tpdd node.
		@param ss   : the sign attached to the short edge.
		@param so   : the sign attached to the open edge.
		@param LT   : the pointer to the left reduced graph.
		@param RT   : the pointer to the right reduced graph.
	*/
		tpddnode(int SymbI, int ss, int so, subtree * LT, subtree *RT);

	/**
		The destructor of a tpdd node.		
	*/
		~tpddnode();

	/**
		Get the number of nodes in the left reduced graph.
	*/
		inline int GetNumLeftNodes()	{return pLTree->GetNumNodes();}

	/**
		Get the number of nodes in the right reduced graph.
	*/
		inline int GetNumRightNodes()	{return pRTree->GetNumNodes();}

	/**
		Get the number of edges in the left reduced graph.
	*/	
		inline int GetNumLeftEdges()	{return pLTree->GetNumEdges();}

	/**
		Get the number of edges in the right reduced graph.
	*/		
		inline int GetNumRightEdges()	{return pRTree->GetNumEdges();}

	/**
		Get the sign of the left reduced graph.
	*/	
		inline int GetLeftSign()		{return pLTree->GetSign();}

	/**
		Get the sign of the right reduced graph.
	*/
		inline int GetRightSign()		{return pRTree->GetSign();}
		
	/**
		Get the next tpdd node in TPDD reducing.
		@return a point to a tpdd node
	*/
		inline tpddnode* GetNextPoint()     {return pNext;}

	/**
		Get the label tag of a tpdd node.
		@return the label tag
	*/
		inline tpddnode_tag * GetTag()	{return &pTag;}
		
	/**
		Get the number of the terms representing by the subgraph rooted by this tpdd node.
	*/	
		inline double GetTermN() {return termN;};

	/**
		Get the index of the symbol of this tpdd node.
	*/
		inline int GetSymbIndex()		{return symbIndex;}
	
	/**
		Get the sign attached to the short edge.
	*/	
		inline int GetSignS()			{return signS;}
	
	/**
		Get the sign attached to the open edge.
	*/	
		inline int GetSignO()			{return signO;}
		
	/**
		Get the edge array of the left reduced graph.
	*/	
		inline EdgeInfo* GetLeftTree()	{return pLTree->GetSubTree();}

    /**
		Get the edge array of the right reduced graph.
	*/
		inline EdgeInfo* GetRightTree() {return pRTree->GetSubTree();}
	
	/**
		Get the pointer to the left reduced graph.
	*/	
		inline subtree* GetLeftSubTree(){return pLTree;}

	/**
		Get the pointer to the right reduced graph.
	*/
		inline subtree* GetRigthSubTree(){return pRTree;}

	/**
		Get the pointer to tpdd node pointed by the short edge.
	*/
		inline tpddnode* GetPShort()	{return pShort;}

	/**
		Get the pointer to tpdd node pointed by the open edge.
	*/
		inline tpddnode* GetPOpen()		{return pOpen;}
		
    /**
		Get the highest order of the s-variable of the expression 
		represented by the subgraph rooted by this tpdd node.
	*/
		inline short GetOrder() {return order;}

	/**
		Set the sign attached to the short edge.
		@param s: the sign of the short edge.
	*/
		inline void SetSignS(int s)		{signS = s;}

	/**
		Set the sign attached to the open edge.
		@param o: the sign of the short edge.
	*/
		inline void SetSignO(int o)		{signO = o;}

	/**
		Set the next tpdd node in TPDD reducing.
		@param pn: the point to the next tpdd node
	*/
		inline void SetNextPoint(tpddnode *pn)		{pNext = pn;}

	/**
		Set the pointer to tpdd node pointed by the short edge.
		@param ps: the point to the tpdd node pointed by the short edge.
	*/
		inline void SetPShort(tpddnode *ps)		{pShort = ps;}

	/**
		Set the pointer to tpdd node pointed by the open edge.
		@param po: the point to the tpdd node pointed by the open edge.
	*/
		inline void SetPOpen(tpddnode *po)		{pOpen = po;}

	/**
		Set the highest order of the s-variable of the expression 
		@param o: the highest order of the s-variable of the expression.
	*/
		inline void SetOrder(short o) {order = o;}

	/**
		Print the infos of a tpdd node
		@param out: the object of the output stream.
	*/
		void PrintTpddNode(std::ostream &out);

	/**
	    The function to identify the type of this class
		@return TPDDNODE
	*/
		virtual integer isa() {return TPDDNODE;}
	
	/**
	    The function to get the hash value.
	*/
		virtual unsigned Hash(unsigned i = 0);

	/**
	    The function to compare two tpdd nodes with the same hash value.
		@param p: the tpdd node with the same hash value with this tpdd node.
	*/
		virtual integer Compare(Comparable *p);
	
	/**
	    The function to get the entry of the hash table.
	*/
		unsigned HashTreeID();

	/**
	    Get the complex_t value of the expression represented by
		the subgraph rooted by this tpdd node.
	*/
		inline complex_t GetValue() {return *val_ptr;}

	/**
	    Get the point to the complex_t value of the expression represented by
		the subgraph rooted by this tpdd node.
	*/
		inline complex_t *GetValueP() {return val_ptr;}

	/**
	    Set the complex_t value of the expression represented by
		the subgraph rooted by this tpdd node.
		@param value: the complex_t value to be assigned.
	*/
		inline void SetValue(complex_t value)  { *val_ptr = value; }

	/**
	    Set the point to the complex_t value of the expression represented by
		the subgraph rooted by this tpdd node.
	*/
		inline void SetValueP(complex_t *val_ptr0) { this->val_ptr = val_ptr0; }

	/**
	    Get the visit flag.
	*/
		inline bool GetVisitFlag() { return visit_flag; }

	/**
	   Set the visit flag.
	   @param visited: the visit flag to be assigned.
	*/
		inline void SetVisitFlag(bool visited)  { visit_flag = visited; }

	/**
		Set the pointer to the left reduced graph.
	*/
		inline void SetLeftTree(subtree *pl) {pLTree = pl;}

	/**
		Set the pointer to the right reduced graph.
	*/
		inline void SetRightTree(subtree *pr) {pRTree = pr;}

	/**
		Set the number of the terms representing by the subgraph rooted by this tpdd node.
	*/
		inline void SetTermN(double d) {termN = d;};
};


/**
	The class of the nodes for the coefficients of the s-variable.
*/
class scoeffNode : public Tnode//public Comparable
{
public:
	///	the point to the expanded tpdd node.
	sexpTpddNode *pNode;

	/// the point to the scoeffNode pointed by the short edge.
	scoeffNode *pShort;

	/// the point to the scoeffNode pointed by the open edge.	
	scoeffNode *pOpen;

	/// the pointer to the complex_t value of the expression.
	complex_t *val_ptr;

	/** 
		the label of the scoeffNodes when reducing the decision diagram of
		the coefficents of the s-variable.
	 */
	int label;

	double termN;

	/**
		the constructor of scoeffNode.
		@param pNode:	the pointer to the expanded tpdd node.
		@param pShort:	the pointer to the scoeffNode pointed by the short edge.
		@param pOpen:   the pointer to the scoeffNode pointed by the open edge.
		@param val_ptr:	the pointer to the complex_t value of the expression.
	 */
	scoeffNode(): Tnode(),
		pNode(0), pShort(0), pOpen(0), val_ptr(new complex_t(0.0)), termN( -1)
	{}

	/**
		the destructor of the scoeffNode.
	 */
	~scoeffNode();

	/**
		The function to identify the type of this class
		@return SCOEFFNODE
	 */
	virtual integer isa() {return SCOEFFNODE;}

	/**
		The function to get the hash value.
	 */
	virtual unsigned Hash(unsigned i = 0);

	/**
		The function to compare two scoeffNodes with the same hash value.
		@param p: the scoeffNode with the same hash value with this scoeffNode.
	 */
	virtual integer Compare(Comparable *p);

	/**
		The function to get the entry of the hash table.
	 */
	unsigned HashTreeID();

	/**
		Get the complex_t value of the expression.
	 */
	complex_t GetValue();

	/**
		Get the pointer to the complex_t value of the expression.
	 */
	complex_t *GetValueP();
#if 0
	void print() const
	{
		std::printf("\n{%p, %p, %p, %p, %p, %6d, %.6E}", this, pNode, pShort, pOpen, val_ptr, label, termN);
	}
#endif
} ;

/**
	The class for the expanded nodes of tree pair decision diagram.
	All the lumped symbols are expanded into identical nodes in the 
	expanded tree pair decision diagram.
*/
class sexpTpddNode : public Tnode//public Comparable
{
public:
	/// the pointer to the expanded tpdd node pointed by the short edge.
	sexpTpddNode* pShort;

	/// the pointer to the expanded tpdd node pointed by the open edge.
	sexpTpddNode* pOpen;

	/// the pointer to the corresponding tpdd node (may have lumped symbols).
	tpddnode    * pTpddNode;

	/// the index of the symbol.
	int symbIndex : 24;

	/// the sign attached to the short edge.
	short signS		: 2;

	/// the sign attached to the open edge.
	short signO		: 2;

	/// the visit flag.
	bool visit_flag : 1;
					
	/// the number of the terms in the expanded tree pair decision diagram.
	double termN;

	/// the list of the coefficients for the different orders of s-variable.
	std::vector<scoeffNode*> *sCoeffList;

	/// the list of the order of the coefficents of s-variable.
	std::vector<int>        *sPowerList;

	double* symbAppearTime;

#if 0
	static int cnt;
	int id;
#endif

public:
	/**
		the default constructor for the nodes of the expanded tree pair decsion diagram.
	*/
	sexpTpddNode();

	/**
		the constructor for the nodes of the expanded tree pair decsion diagram.
		@param pS: the pointer to the sexpTpddNode node pointed by the short edge.
		@param pO: the pointer to the sexpTpddNode node pointed by the open edge.
		@param pT: the pointer to the corresponding tpdd node.
		@param sn: the index of the symbol.
		@param ss: the sign attached to the short edge.
		@param so: the sign attached to the open edge.
	*/
	sexpTpddNode(sexpTpddNode* pS, sexpTpddNode* pO, tpddnode* pT, int sn, short ss, short so);

	/**
		the destructor for the nodes of the expanded tree pair decsion diagram.
	*/
	~sexpTpddNode();

	/**
	    The function to identify the type of this class
		@return SEXPTPDDNODE
	*/
	virtual integer isa() {return SEXPTPDDNODE;}

	/**
	    The function to get the hash value.
	*/
	virtual unsigned Hash(unsigned i = 0);

	/**
	    The function to compare two sexpTpddNode with the same hash value.
		@param p: the sexpTpddNode with the same hash value with this sexpTpddNode.
	*/
	virtual integer Compare(Comparable *p);

	/**
	    The function to get the entry of the hash table.
	*/
	unsigned HashTreeID();

	sexpTpddNode* GetPShort(){return pShort;}

	sexpTpddNode* GetPOpen(){return pOpen;}
};

#endif 

